#ifndef _TRACE_H
#define _TRACE_H

typedef short trace_level_t;

const trace_level_t T_FATAL = 1;
const trace_level_t T_ERR = 2;
const trace_level_t T_WARN = 4;
const trace_level_t T_INFO = 8;
const trace_level_t T_DEBUG = 16;

#ifdef __GNUC__
#define PRINTF_ARGS(X, Y) __attribute__((format(printf, X, Y)))
#else
#define PRINTF_ARGS(X, Y)
#endif

#define TFATAL(fmt...) trace(T_FATAL, __func__, __LINE__, fmt)
#define TERR(fmt...) trace(T_ERR, __func__, __LINE__, fmt)
#define TWARN(fmt...) trace(T_WARN, __func__, __LINE__, fmt)
#define TINFO(fmt...) trace(T_INFO, __func__, __LINE__, fmt)
#define TDEBUG(fmt...) trace(T_DEBUG, __func__, __LINE__, fmt)
#define TRACE(level, fmt...) trace(level, __func__, __LINE__, fmt)

void set_trace_level(trace_level_t l);

void trace(trace_level_t level, const char * function, int line, const char *formatstring, ...) PRINTF_ARGS(4, 5);

#endif
